
// Director-> set custom parameters ;   
// Builder->hide the BuiltObject 's create logical(BuiltObject::Ctor)
// BuiltObject(TailSource, TailFollowSource)-> logical's 

#[derive(Debug)]
struct TailSource {
    fname: String,
    lines: u64,
}
impl TailSource {
    fn new(fname: String, lines: u64) -> Self {
        Self {
            fname,
            lines
        } 
    }
}
impl TailSource {
    fn process(&self){
        println!("TailSource:[{:?}]-process!", self);
    }
}
#[derive(Debug, Default)]
struct TailSourceBuilder {
    fname: Option<String>,
    lines: Option<u64>,
}
impl TailSourceBuilder {
    fn set_fname(&mut self, fname: &str) -> &mut Self {
        self.fname = Some(fname.to_owned());
        self
    }
    fn set_lines(&mut self, lines: u64) -> &mut Self {
        self.lines = Some(lines);
        self
    }
    fn build(self) -> TailSource {
        TailSource::new(
            self.fname.unwrap_or("main.rs".to_owned()),
            self.lines.unwrap_or(10)
        )
    }
}


#[derive(Debug)]
struct TailFollowSource {
    fname: String,
    interval_ms: u64,
}
impl TailFollowSource {
    fn new(fname: String, interval_ms: u64) -> Self{
        Self {
            fname,
            interval_ms
        }
    }
}
impl TailFollowSource {
    fn process(&self){
        println!("TailFollowSource:[{:?}]-process!", self);
    }
}
#[derive(Debug, Default)]
struct TailFollowSourceBuilder {
    fname: Option<String>,
    interval_ms: Option<u64>,
}
impl TailFollowSourceBuilder {
    fn set_fname(&mut self, fname: &str) -> &mut Self {
        self.fname = Some(fname.to_owned());
        self
    }
    fn set_interval_ms(&mut self, interval_ms: u64) -> &mut Self {
        self.interval_ms = Some(interval_ms);
        self
    }
    fn build(self) -> TailFollowSource {
        TailFollowSource::new(
            self.fname.unwrap_or("main.rs".to_owned()),
            self.interval_ms.unwrap_or(1000)
        )
    }
}


#[derive(Debug, Default)]
struct Director {
}
impl Director {
    fn construct_tail_source(&self, tail_builder:&mut TailSourceBuilder){
        tail_builder
            .set_fname("main.rs")
            .set_lines(100);
    }
    fn construct_tail_follow_source(&self, follow_builder:&mut TailFollowSourceBuilder) {
        follow_builder
            .set_fname("new_main.rs")
            .set_interval_ms(2000);
    }
}







//write an demo for acsvr builder; 
// ServerDirector -> get & set parameters 
// Adapt the ctor's interface  for all Components of AccessServer
// Components 

#[derive(Debug, Default)]
struct Safe {
    cert: String,
}
#[derive(Debug, Default)]
struct SafeBuilder{
    cert: Option<String>
}
impl SafeBuilder{
    fn build(self) -> Safe{
        Safe{
            cert: self.cert.unwrap(),
        }
    }   
    fn set_cert(&mut self, cert: &str) -> &mut Self{
        self.cert = Some(cert.to_owned());
        self
    }
}


#[derive(Debug, Default)]
struct ProtocolConverter {
    file_path: String,
    field_map: std::collections::HashMap<String, String>,
}
#[derive(Debug, Default)]
struct ProtocolConverterBuilder{
    file_path: Option<String>,
}
impl ProtocolConverterBuilder{
    fn set_file_path(&mut self, file_path: &str){
        //load file 
        println!("load protocol converter field-to-field mapping");
        self.file_path = Some(file_path.to_owned());
    }
    fn build(self) -> ProtocolConverter{
        ProtocolConverter {
            file_path: self.file_path.unwrap(),
            field_map: std::collections::HashMap::new(),
        }
    }   
}

#[derive(Debug, Default)]
struct FrameWork {
    address: String,
}

#[derive(Debug, Default)]
struct FrameworkBuilder {
    address: Option<String>
}
impl FrameworkBuilder{
    fn set_address(&mut self, address: &str) {
        self.address = Some(address.to_owned())
    }
    fn build(self) -> FrameWork{
        FrameWork{
            address: self.address.unwrap(),
        }
    }   
}


#[derive(Debug, Default)]
struct TraderAcessServeDirector {
    cfg_file_path: String,
    cfg_map: std::collections::HashMap<String, String>,
}
impl TraderAcessServeDirector {
    fn construct_safe(&self, builder: &mut SafeBuilder){
        //get safe config block from local file
        builder.set_cert("This is an Cert Data");
    }
    fn construct_protocol_converter(&self, builder: &mut ProtocolConverterBuilder){
        //get protocol config block from local file
        // fname = self.cfg_map["protoco_cvt_mapping_file"]
        builder.set_file_path("new_proto_cvt_mapping");
    }
    fn construct_frame_work(&self, builder: &mut FrameworkBuilder){
        builder.set_address("192.168.0.1:8080");
        //get framework config block from local file
    }
}


#[derive(Debug, Default)]
struct App {
    director: TraderAcessServeDirector,
    safe: Safe,
    proto_cvt: ProtocolConverter,
    framework: FrameWork,
}
impl App {
    fn construct(&mut self) -> &mut Self{
        let mut safe_builder = SafeBuilder::default();
        self.director.construct_safe(&mut safe_builder);
        self.safe = safe_builder.build();

        let mut protocol_converter_builder = ProtocolConverterBuilder::default();
        self.director.construct_protocol_converter(&mut protocol_converter_builder);
        self.proto_cvt = protocol_converter_builder.build();

        let mut framework_builder = FrameworkBuilder::default();
        self.director.construct_frame_work(&mut framework_builder);
        self.framework = framework_builder.build();
        self
    }

    fn run(&mut self) -> &mut Self {
        self
    }
}




#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_sever(){
        let mut app = App::default();
        app.construct().run();
    }

    #[test]
    fn test_main(){
        let director = Director::default();

        let mut tail_builder = TailSourceBuilder::default();
        director.construct_tail_source(&mut tail_builder);
        tail_builder.build().process();

        let mut follow_builder = TailFollowSourceBuilder::default();
        director.construct_tail_follow_source(&mut follow_builder);
        follow_builder.build().process();
    }
}